
package autorization;

import baseservergrid.ModeCompilation;
import java.io.File;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import mpiserver.Settings;

/**
 * Класс  предназначен для настройки пользователей в операционной системе.
 * Предоставляет сервисы добавления/удаления группы/пользователя,
 * установки прав доступа для группы/пользователя.
 * Класс спроектирован с использованием паттерна Singleton.
 * @author Aleksey ID=2001
 */
public class OSUsers {
    /** имя группы пользователей */
    private static final String GROUP_NAME="gfdgroup";
    /** имя пользователя */
    private static final String USER_NAME="gfduser";

    /** объект класса */
    private static OSUsers instance=null;

    //строка вызова скрипта для создания группы
    private String scrCreateGroup="";
    //строка вызова скрипта для создания группы
    private String scrRemoveGroup="";
    //строка вызова скрипта для создания пользователя
    private String scrCreateUser="";
    //строка вызова скрипта для удаления пользователя
    private String scrRemoveUser="";
    //регистрация в MPI сервере
    private String scrRegisterInMpi="";

    //путь до директории со скриптами
    private String scriptsPath="";
    //путь до настроичного файла
    private String settingsPath="";

    /**
     * Запросить имя группы пользователей
     * @return имя группы пользователей
     */
    public static String getGroupName(){
        return GROUP_NAME;
    }

    /**
     * Запросить имя пользователя в системе
     * @param userID идентификатор пользователя
     * @return имя пользователя
     */
    public static String getUserName(long userID){
        return USER_NAME+Long.toString(userID);
    }

    /**
     * Запросить объект класса
     * @return объект класса
     */
    public static OSUsers getInstance(){
        if(instance==null) instance=new OSUsers();
        return instance;
    }

    /**
     * Конструктор
     */
    private OSUsers(){
        settingsPath="."+File.separator+"usersconfig"+File.separator+"config.ini";
    }


    /**
     * Прочитать строку скрипта и заменить статическае свойства
     * @param iniReader парсер файла настроек
     * @param scrName имя свойства строки вызова скрипта
     * @param scrVars имена свойтв статических переменных
     * @return строка вызова скрипта
     * @throws java.lang.Exception ошибка при чтении свойств
     */
    private String readScr(Settings iniReader,String scrName,String... scrVars)
            throws Exception{
        //прочитать строку скрипта
        String tmpStr=iniReader.getField(scrName);
        //заменить статические переменные
        for(String varStr:scrVars)
            tmpStr=tmpStr.replace(varStr, iniReader.getField(varStr));
        return tmpStr;
    }

    /**
     * Прочитать командные строки вызова скриптов
     * @return true в случае успеха, иначе false
     */
    public boolean config() {
        return setSettings(getSettings());
    }

    /**
     * Запросить парсер с загруженными настройками
     * @return парсер с настройками
     */
    public Settings getSettings(){
        //получить файл настроек
        Settings iniReader=new Settings(settingsPath);
        iniReader.loadFile();
        return iniReader;
    }

    /**
     * Установить настройки
     * @param iniReader парсер с загруженными настройками
     * @return true в случае успеха
     */
    public boolean setSettings(Settings iniReader){
        //считать скрипты
        try {
            //считать скрипт создания группы
            scrCreateGroup=readScr(iniReader,"group_add","@SCRDIR@");
            //считать скрипт удаления группы
            scrRemoveGroup=readScr(iniReader,"group_del","@SCRDIR@");
            //считать скрипт создания пользователя
            scrCreateUser=readScr(iniReader,"user_add","@SCRDIR@");
            //считать скрипт создания пользователя
            scrRemoveUser=readScr(iniReader,"user_del","@SCRDIR@");
            //считать скрипт для регистрации пользователя в mpi
            scrRegisterInMpi=readScr(iniReader,"register_mpi","@SCRDIR@","@MPI@");
            //запросить директрию скриптов
            scriptsPath=iniReader.getField("@SCRDIR@");
        } catch (Exception ex) {
            return false;
        }
        return true;
    }

    /**
     * Создать группу пользователей
     * @return true - скрипт вызван, false - ошибка вызова
     */
    public boolean createGroup(){
        String tmpStr=scrCreateGroup;
        try{
            //подставить параметры в вызов командной строки
            tmpStr=tmpStr.replace("%GNAME%",GROUP_NAME);
            //запустить выполнение скрипта
            if(ModeCompilation.OSENABLE)
                Runtime.getRuntime().exec(tmpStr);
        } catch (Exception ex) { //ошибка вызова командной строки
            return false;
        }
        return true;
    }

    /**
     * Удалить группу пользователей
     * @return true - скрипт вызван, false - ошибка вызова
     */
    public boolean removeGroup(){
        String tmpStr=scrRemoveGroup;
        try{
            //подставить параметры в вызов командной строки
            tmpStr=tmpStr.replace("%GNAME%",GROUP_NAME);
            //запустить выполнение скрипта
            if(ModeCompilation.OSENABLE)
                Runtime.getRuntime().exec(tmpStr);
        } catch (Exception ex) { //ошибка вызова командной строки
            return false;
        }
        return true;
    }

    /**
     * Создать пользователя с нулевыми правами
     * @param userID
     * @return true - скрипт вызван, false - ошибка вызова
     */
    public boolean createUser(long userID){
        String tmpStr=scrCreateUser;
        try{
            //подставить параметры в вызов командной строки
            tmpStr=tmpStr.replace("%GNAME%",GROUP_NAME);
            tmpStr=tmpStr.replace("%UNAME%",getUserName(userID));
            tmpStr=tmpStr.replace("%UPWD%","123"); //Заглушка
            //запустить выполнение скрипта
            if(ModeCompilation.OSENABLE)
                Runtime.getRuntime().exec(tmpStr);
        } catch (Exception ex) { //ошибка вызова командной строки
            return false;
        }
        return true;
    }

    /**
     * Удалить пользователя
     * @param userID идентификатор пользователя
     * @return true - скрипт вызван, false - ошибка вызова
     */
    public boolean removeUser(long userID){
        String tmpStr=scrRemoveUser;
        try{
            //подставить параметры в вызов командной строки
            tmpStr=tmpStr.replace("%UNAME%",getUserName(userID));
            //запустить выполнение скрипта
            if(ModeCompilation.OSENABLE)
                Runtime.getRuntime().exec(tmpStr);
        } catch (Exception ex) { //ошибка вызова командной строки
            return false;
        }
        return true;
    }

    /**
     * Установить полные права доступа для заданной директории
     * @param userID идентификатор пользователя
     * @param path путь до разрешаемой директории
     * @return true - скрипт вызван, false - ошибка вызова
     */
    public boolean setAllowDir(long userID, String path){
        return true;
    }

    /**
     * Зарегестрировать пользователя в MPI сервере
     * @param userID идентификатор пользователя
     * @return true - скрипт вызван, false - ошибка вызова
     */
    public boolean registerInMpi(long userID){
        String tmpStr=scrRegisterInMpi;
        try{
            //подставить параметры в вызов командной строки
            tmpStr=tmpStr.replace("%UID%",String.valueOf(userID));
            //запустить выполнение скрипта
            if(ModeCompilation.OSENABLE){
                Process proc = Runtime.getRuntime().exec(tmpStr);
                //получить поток ввода
                OutputStreamWriter wtr=new OutputStreamWriter(proc.getOutputStream());
                //передать приложению строку с логином
                wtr.write(getUserName(userID)); wtr.flush();
                //эмуляция нажатия Enter
                wtr.write('\n'); wtr.flush();
                String pwd="123"; //Заглушка !!!
                //посимвольно передать пароль (построчно не работает)
                for(char ch:pwd.toCharArray()){wtr.write(ch); wtr.flush();}
                wtr.write('\n'); wtr.flush();
                //посимвольно передать подтверждение пароля
                for(char ch:pwd.toCharArray()){wtr.write(ch); wtr.flush();}
                wtr.write('\n'); wtr.flush();
            }
        } catch (Exception ex) { //ошибка вызова командной строки
            return false;
        }
        return true;
    }
}
